/*
 * tcu_can.cpp
 *
 *  Created on: 2018-4-9
 *      Author: root
 */
#include "tcu_can.h"
#include "log_main.h"
#include "app_debug_main.h"
#include <sys/ipc.h>
#include <sys/msg.h>
#include "protocol_can.h"
#include "program.h"
#include <linux/can.h>
#include "tools.h"
#include "string.h"
#include "tcu_can.h"
#include "protocol_offset.h"
#include "can_task.h"
#include "meter_com.h"

#ifdef XJ_MQTT_CLIENT
#include "meter_xj.h"
#include "interface_xj.h"
#include "log_main.h"
#endif

#ifdef NW_CLIENT
#include "meter_nw.h"
#include "pro_104.h"
#endif
#ifdef ORDERLY_CHARGE
#include "Interface_dllfk.h"
#endif

#ifdef QL_CLOUD_CLIENT
#include "meter_ql.h"
#include "interface_ql.h"
#endif

Para_Can a_can;
Para_Can *gpcan=&a_can;
can_data g_candata;
start_mx g_startInfo[GUN_NUM];
canlink* g_pcan[]={NULL,NULL};
//canxxx  * pcan1;
//canxxx  *pcan2;
//int g_qmegid[]={-1,-1};
//unsigned char port;	// 端口号 0,1
//unsigned char cha_addr;	// 控制器can地址 默认0xf6
//unsigned char tcu_addr;	//tcu地址 默认0x8a
//unsigned char gunno;	   //枪号
Gun_Can_Info gun_can_info_tab[]={
		{0,0,0xE0,0x8a},
		{1,0,0xE0,0x8a},
		{0,2,0xE2,0x8a},
		{0,3,0xE3,0x8a},
		{1,0,0xE0,0x8a},
		{1,1,0xE1,0x8a},
		{1,2,0xE2,0x8a},
		{1,3,0xE3,0x8a},
};

//can 发送失败!!!!!!!!



YX_ERR_WARN yxerr8704_tab[]={
		{DC_IND_EMERSTOP_FAULT_OFFSET,                                                      (char*) "急停按钮动作故障"},
		{DC_IND_SMOKE_ALARM_OFFSET	,                                                         (char*) "烟感故障"},
		{DC_IND_AC_BREAKER_OFFSET,	                                                              (char*) "交流输入断路器故障"},
		{DC_IND_DC_OUT_CONTACTOR_OFFSET,                                               (char*) "直流母线输出接触器拒动/误动故障"},
		{DC_IND_DC_OUT_FUSES_OFFSET,                                                             (char*) "直流母线输出熔断器故障"},
		{DC_IND_INTERFACE_ELE_LOCK_FAULT_OFFSET ,                                (char*) "充电接口电子"},
		{DC_IND_CHARGE_FAN_OFFSET,                                                                 (char*) "充电桩风扇故障"},
		{DC_IND_THUNDERBOLT_OFFSET,                                                             (char*)  "避雷器故障"},
		{DC_IND_INSULATION_OFFSET,                                                                  (char*) "绝缘监测故障"},
		{DC_IND_BATTERY_REVERSE_OFFSET,                                                        (char*) "电池极性反接故障"},
		{DC_IND_CHARGING_CAR_GUIDE_OFFSET,                                              (char*) "充电中车辆控制导引故障"},
		{DC_IND_PILE_OVERTURNED_OFFSET,                                                      (char*) "充电桩过温故障"},
		{DC_IND_GUNS_OVERTURNED_OFFSET,                                                   (char*) "充电接口过温故障"},
		{DC_IND_GUNS_NO_HOMELESS_OFFSET,                                                 (char*) "充电枪未归位告警"},
		{DC_IND_BMS_COMMUNICATION_OFFSET,	                                         (char*) "BMS 通信故障"},
		{DC_IND_INPUT_V_OVER_OFFSET,                                                               (char*) "输入电压过压故障"},
		{DC_IND_INPUT_V_UNDER_OFFSET,                                                            (char*) "输入电压欠压故障"},
		{DC_IND_DC_BUS_OUT_V_OVER_OFFSET,                                                   (char*) "直流母线输出过压故障"},
		{DC_IND_DC_BUS_OUT_V_UNDER_OFFSET,                                                (char*) "直流母线输出欠压故障"},
		{DC_IND_DC_BUS_OUT_A_OVER_OFFSET	,                                                 (char*) "直流母线输出过流故障"},
		{DC_IND_CHARGE_MODULE_OFFSET,                                                          (char*) "充电模块故障"},
		{DC_IND_MODULE_AC_INPUT_OFFSET	,                                                     (char*) "充电模块交流输入故障"},
		{DC_IND_MODULE_AC_IN_V_OVER_OFFSET	,                                          (char*) "充电模块交流输入过压故障"},
		{DC_IND_MODULE_AC_IN_V_UNDER_OFFSET,                                           (char*) "充电模块交流输入欠压故障"},
		{DC_IND_MODULE_AC_IN_PHASE_OFFSET,                                               (char*) "充电模块交流输入缺相故障"},
		{DC_IND_MODULE_DC_OUT_SHORT_OFFSET,                                           (char*) "充电模块直流输出短路故障"},
		{DC_IND_MODULE_DC_OUT_A_OVER_OFFSET	,                                     (char*) "充电模块直流输出过流故障"},
		{DC_IND_MODULE_DC_OUT_V_OVER_OFFSET,                                        (char*) "充电模块直流输出过压故障"},
		{DC_IND_MODULE_DC_OUT_V_UNDER_OFFSET,                                      (char*) "充电模块直流输出欠压故障"},
		{DC_IND_MODULE_OVERTURNED_OFFSET,                                               (char*) "充电模块过温故障"},
		{DC_IND_MODULE_COMMUNICATION_OFFSET,                                     (char*) "充电模块通信故障"},
		{DC_IND_MODULE_FAN_OFFSET,                                                                  (char*) "充电模块风扇故障"},
//        { DC_IND_CONNECT_CAR_OFFSET,(char*) "车辆连接状态"},  	//  0连接  1未连接
//        {DC_IND_GUNS_STATUS_OFFSET,  (char*) "充电桩充电枪座状态"},//  0连接  1未连接
//     	{DC_IND_ELE_LOCK_STATUS_OFFSET,(char*) "充电接口电子锁状态"},// 0解锁  1 锁止
//   	    {DC_IND_DC_OUT_CONTACTOR_STATUS_OFFSET,(char*) "直流输出接触器状态"},//  00H： 分断  01H： 闭合
//     	{DC_IND_PRIVATE_WARN_NUM_OFFSET,(char*) "私有告警编号"},
//   	    {DC_IND_PRIVATE_VALUE_OFFSET	,(char*) "私有告警数值"},
};

YX_ERR_WARN yxerr8960_tab[] = {
		{DC_IND_DOOR_FAULT_OFFSET,                          (char*) "门禁故障" },
		{DC_IND_DC_BUS_OUT_CONTACTOR_ADHESION_FAULT_OFFSET, (char*) "直流输出接触器粘连故障" },
//      {DC_IND_INSULATION_WARN_OFFSET,                   (char*)  "绝缘监测告警" },
        {DC_IND_DISCHARGE_LOOP_WARN_OFFSET,                (char*) "泄放回路故障" },
//		{DC_IND_CHARGE_PILE_OVERTURNED_WARN_OFFSET,        (char*) "充电桩过温告警" },
//      {DC_IND_CHARGE_GUN_OVERTURNED_WARN_OFFSET,         (char*) "充电枪过温告警" },
		{DC_IND_AC_IN_CONTACTOR_ERR_ACTION_OFFSET,         (char*) "交流输入接触器据动/误动故障" },
		{DC_IND_AC_IN_CONTACTOR_ADHESION_FAULT_OFFSET,     (char*) "交流输入接触器粘连故障" },
		{DC_IND_ASSIST_POWER_FAULT_OFFSET,                 (char*) "辅助电源故障" },
		{DC_IND_PARALLEL_CONTACTOR_ERR_ACTION_OFFSET,      (char*) "并联接触器据动/误动故障" },
		{DC_IND_PARALLEL_CONTACTOR_ADHESION_FAULT_OFFSET,  (char*) "并联接触器粘连故障" },
		{DC_IND_POWER_CTRL_MODULE_COMM_FAULT_OFFSET,       (char*) "功率模块通信故障"},
		{DC_IND_POWER_CTRL_MODULE_FAULT_OFFSET,            (char*) "功率模块故障"},
		{DC_IND_SWITCH_MODULE_COMM_FAULT_OFFSET,      (char*) "开关模块通信故障"},
		{DC_IND_SWITCH_MODULE_FAULT_OFFSET,           (char*) "开关模块故障"},
		{DC_IND_CONTROLER_BMS_FAULT_OFFSET,           (char*) "直流充电主控模块判断BMS故障"},
		{DC_IND_MODULE_LOOP_FAULT_OFFSET,             (char*) "充电模块泄放故障"},
		{DC_IND_INSULATION_DEVICE_COMM_FAULT_OFFSET,  (char*) "绝缘检测仪通信故障"},
		{DC_IND_ENVI_MONITOR_COMM_FAULT_OFFSET,       (char*) "环境监控板通信故障"},
};

YX_ERR_WARN yxerr12800_tab[] = {
//		{AC_IND_TOTAL_FAULT_OFFSET	,"总故障"},//
//		{AC_IND_TOTAL_WARN_OFFSET,"总告警"},	//                                                                        3               //
//		{AC_IND_CONNECT_SWITCH_OFFSET,	"车辆连接状态"}	,   //                                                4               //
		{AC_IND_EMERSTOP_OFFSET	,                                                              (char*) "急停按钮动作故障"	},	//                                                        5               //
		{AC_IND_THUNDERBOLT_OFFSET,	                                                       (char*) "避雷器故障"}	 ,  //                                                        6               //
		{AC_IND_GUNS_NO_HOMELESS_OFFSET,	                                           (char*)"充电枪未归位告警"}	 ,  //                                    7               //
		{AC_IND_OVERTHRNED_OFFSET,	                                                           (char*) "充电桩过温故障"}	,   //                                                    8               //
		{AC_IND_INPUT_V_OVER_OFFSET,                                                         (char*) 	"输入电压过压故障"}	 ,       //                                           9         //
		{AC_IND_INPUT_V_UNDER_OFFSET,	                                                   (char*) "输入电压欠压故障"	}  ,   //                                         10              //
		{AC_IND_OUT_CONTACTOR_STATUS_OFFSET,                                    (char*) "交流输出接触器状态"}  , //                          11              //
		{AC_IND_CHARGING_CAR_GUIDE_OFFSET,                                  	   (char*) "充电中车辆控制导引故障"  } , //                     12              //
		{AC_IND_AC_CONTACTOR_OFFSET,	                                                       (char*) "交流输出接触器拒动/误动故障"},//	                            13              //
//		{AC_IND_OUT_A_OVER_ALARM_OFFSET,	"输出过流告警"}	,   //                                              14              //
		{AC_IND_OUT_A_OVER_FAULT_OFFSET	,                                              (char*) "输出过流故障"} ,   //                                                 15              //
		{AC_IND_AC_BREAKER_OFFSET,	                                                           (char*) "交流输入断路器故障"	},     //                                               16              //
		{AC_IND_INTERFACE_ELE_LOCK_OFFSET,                                            (char*) "充电接口电子锁状态"	} , //                                  17              //
		{AC_IND_INTERFACE_ELE_LOCK_FAULT_OFFSET,                              (char*) "充电接口电子锁故障"},	  //                         18              //
		{AC_IND_INTERFACE_OVERTURNED_OFFSET,	                                   (char*) "充电接口过温故障" } ,   //                              19              //
//		{AC_IND_CHARGING_CONNECT_STATUS_OFFSET,"充电连接状态CC"	  } ,   //                           20              //
//		{AC_IND_CHARGING_CONTROL_STATUS_OFFSET,"充电控制状态CP"	}  ,    //                          21              //
		{ AC_IND_PE_DISCONNECT_OFFSET,                                              	  (char*) "PE 断线故障"	} , //                                                           23               //
		{AC_IND_DOOR_FAULT_OFFSET,                                                            (char*) "门禁故障" }  ,         //                                                              24               //
//		{ AC_IND_CHARGE_PILE_OVERTURNNED_WARN_OFFSET,  "充电桩过温告警" },   //                25               //
//		{AC_IND_CHARGE_INTERFACE_OVERTURNNED_WARN_OFFSET, "充电接口过温告警"} , //    26               //
		{AC_IND_OUT_CONTACTOR_ADHESION_FAULT_OFFSET,             (char*) "交流输出接触器粘连故障"}  , //       27              //
//		{AC_IND_GENERAL_ALARM_FAULT_OFFSET,	   "通用告警和故障" }  ,   //                                    28               //
//		{AC_IND_PRIVATE_WARN_NUM_OFFSET ,"私有告警编号" } ,  //                                                   29               //
//		{AC_IND_PRIVATE_WARN_VALUE_OFFSET, "私有告警数值"} ,   //                                                  30               //
};



void print_frame(CanMsg *fr)
{
//	int i;
//	printf("%08x\n", fr->can_id & CAN_EFF_MASK);
//	//printf("%08x\n", fr->can_id);
//	printf("dlc = %d\n", fr->can_dlc);
//	printf("data = ");
//	for (i = 0; i < fr->can_dlc; i++)
//		printf("%02x ", fr->data[i]);
//	printf("\n");
}


void handle_err_frame(CanMsg *fr)
{
	if (fr->can_id & CAN_ERR_TX_TIMEOUT) {
		errout("CAN_ERR_TX_TIMEOUT");
	}
	if (fr->can_id & CAN_ERR_LOSTARB) {
		errout("CAN_ERR_LOSTARB");
		errcode(fr->data[0]);
	}
	if (fr->can_id & CAN_ERR_CRTL) {
		errout("CAN_ERR_CRTL");
		errcode(fr->data[1]);
	}
	if (fr->can_id & CAN_ERR_PROT) {
		errout("CAN_ERR_PROT");
		errcode(fr->data[2]);
		errcode(fr->data[3]);
	}
	if (fr->can_id & CAN_ERR_TRX) {
		errout("CAN_ERR_TRX");
		errcode(fr->data[4]);
	}
	if (fr->can_id & CAN_ERR_ACK) {
		errout("CAN_ERR_ACK");
	}
	if (fr->can_id & CAN_ERR_BUSOFF) {
		errout("CAN_ERR_BUSOFF");
	}
	if (fr->can_id & CAN_ERR_BUSERROR) {
		errout("CAN_ERR_BUSERROR");
	}
	if (fr->can_id & CAN_ERR_RESTARTED) {
		errout("CAN_ERR_RESTARTED");
	}
}

int can_recv_form_cha(int fd,int qid)
{
	int ret;
	CanMsg frdup;
	struct timeval tv;
	msgtcu msgs;
	fd_set rset;
	int lenmsg;
	lenmsg=sizeof(CanMsg);
	while (1) {
	//	sleep(1);
		tv.tv_sec = 2;
		tv.tv_usec = 0;
		FD_ZERO(&rset);
		FD_SET(fd, &rset);
		ret = select(fd+1, &rset, NULL, NULL, &tv);
		if (ret == 0) {
			myerr("select time out");
			continue;
		}
		ret = read(fd, &frdup,lenmsg );
		if (ret < lenmsg) {
			myerr("read failed");
			continue;
		}
		if (frdup.can_id & CAN_ERR_FLAG) {/* 出错设备错误 */
			handle_err_frame(&frdup);
			myerr("CAN device error");
			continue;
		}
		msgs.msgtype=1;
		can_debug("ret=%d  size=%d   msgs=%d\r\n",ret,sizeof(frdup),sizeof(msgtcu));
	    memcpy(msgs.pmsg,(char*)&frdup,sizeof(frdup));
	    if (msgsnd(qid, &msgs, sizeof(msgtcu), IPC_NOWAIT) != -1)//
	    {
	  //  	can_debug("发送 succ succ succ succ !!!!!!!\r\n");
	    }
	}
	return 0;
}

int init_can(int chan, int samplate) {
	char cmd[256] = {0};
	int status = 0;

	if (chan != 0 && chan != 1) {
        printf("%s fault: para error!", __func__);
        return -1;
	}
	// can down
	sprintf(cmd, "ip link set can%d down", chan);
	system(cmd);
	if (WEXITSTATUS(status)) {
		printf("%s :failed status: %d, %s", cmd, status, strerror(errno));
		return -1;
	}

	//set can bitrate
	sprintf(cmd, "ip link set can%d type can bitrate %d triple-sampling on", chan, samplate);
	system(cmd);
	if (WEXITSTATUS(status)) {
		printf("%s :failed status: %d, %s", cmd, status, strerror(errno));
		return -1;
	}

	//can up
	sprintf(cmd, "ip link set can%d up", chan);
	system(cmd);
	if (WEXITSTATUS(status)) {
		printf("%s :failed status: %d, %s", cmd, status, strerror(errno));
		return -1;
	}

	//set tx buffer length
	sprintf(cmd, "echo 16384 > /sys/class/net/can%d/tx_queue_len", chan);
	system(cmd);
	if (WEXITSTATUS(status)) {
		printf("%s :failed status: %d, %s", cmd, status, strerror(errno));
		return -1;
	}

    return 0;
}

int initcansocket(u8 port,int* pS)
{
 	int s=*pS;
    int ret;
    struct sockaddr_can addr;
    struct ifreq ifr;
	srand(time(NULL));

	s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
	if (s < 0) {
		perror("socket PF_CAN failed");
		return 1;
	}

	//关闭回环
	int loopback = 0;
	setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

	can_err_mask_t err_mask;
	err_mask = (CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF);
	setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask));

if(port==0)
    strcpy(ifr.ifr_name, "can0");
else
	strcpy(ifr.ifr_name, "can1");

	ret = ioctl(s, SIOCGIFINDEX, &ifr);
	if (ret < 0) {
		perror("ioctl failed");
		return 1;
	}

	addr.can_family = PF_CAN;
	addr.can_ifindex = ifr.ifr_ifindex;
	ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
	if (ret < 0) {
		perror("bind failed");
		return 1;
	}

	*pS=s;

	can_debug("can初始化成功1111111111111 %d port=%d",s,port);
	return 0;
}
u8 getChargeState(u8 gunid)
{
       u8 charge_state;
////   if(gunid==0 )
   //    ui_debug1("获得枪的充电状态 摇信 %.*a gunid=%d",8,g_candata.gun[gunid].yx_data.yx_ac_pf32,gunid);
    	if(pconfig->devtype==DC)
    	{
    	    charge_state=g_candata.gun[gunid].yx_data.yx_dc_pf22[1]&0x03;
    	}
    	else if(pconfig->devtype==AC)
    	{

    	    charge_state=g_candata.gun[gunid].yx_data.yx_ac_pf32[1]&0x03;
    	}
    	else
    		charge_state=0;

    	return charge_state;
}

u8 getCpState(u8 gunid)
{
	u8 state=0;
    u8 tabid;
    u8 offset;
    tabid=AC_IND_CHARGING_CONTROL_STATUS_OFFSET/8+1;
    offset=AC_IND_CHARGING_CONTROL_STATUS_OFFSET%8-1;

    if(pconfig->devtype==AC)
    {
    	state=g_candata.gun[gunid].yx_data.yx_ac_pf32[tabid]&0x03;
    }

    return state;

}
u8 writeErrToDb(u8 gunid,u8 type)
{
	TDateTime datetime;
	err_record e_rd;
	read_current_datetime(&datetime);
    e_rd.time[6]=byte2bcd(datetime.Sec);//交易时间
    e_rd.time[5]=byte2bcd(datetime.Min);
    e_rd.time[4]=byte2bcd(datetime.Hour);
    e_rd.time[3]=byte2bcd(datetime.Day);
    e_rd.time[2]=byte2bcd(datetime.Month);
    e_rd.time[1]=byte2bcd(datetime.Year%100);
    e_rd.time[0]=byte2bcd(datetime.Year/100);
    e_rd.type=type;
    e_rd.guntab=gunid;
    ui_debug("故障发生时间：%.*a",7,e_rd.time);
    protocol_updateERR(&e_rd);
    return 0;
}

u8 get_gun_conn_state(u8 gunid)//获得充电枪连接状态
{
    u8 conn_state=0;
    u8 tabid;
    u8 offset;
	if(pconfig->devtype==DC)
	{
		tabid=DC_IND_CONNECT_CAR_OFFSET/8+1;
		offset=DC_IND_CONNECT_CAR_OFFSET%8;
		conn_state=(g_candata.gun[gunid].yx_data.yx_dc_pf22[tabid]>>offset)&0x01;
	}
	else if(pconfig->devtype==AC)
	{
		tabid=AC_IND_CONNECT_SWITCH_OFFSET/8+1;
		offset=AC_IND_CONNECT_SWITCH_OFFSET%8;
		conn_state=(g_candata.gun[gunid].yx_data.yx_ac_pf32[tabid]>>offset)&0x01;
	}

	printf("获得充电枪[%d]连接状态 conn_state=%d\r\n", gunid, conn_state);

	return conn_state;

}

u8 get_gun_err_new(u8 gunid,u8* errcodeflag)
{
    u8 err_code=0,err_code_z=0,last_err_code=0;
    u8 tabid;
    u8 offset;
    u8 alloff;
    int i;
    int num;
	u8 err  = 0;//00 04 00 00 00 80 00 01
	u8 err1 = 0;    // 当前最新告警标识 

    static u8 last_temp_pf22[8][8]={{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};
    static u8 last_temp_pf23[8][8]={{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};

//   if( getChargeState(gunid)==2)
//   {
//		tabid=DC_IND_EMERSTOP_FAULT_OFFSET/8+1;
//		offset=DC_IND_EMERSTOP_FAULT_OFFSET%8;
//		err_code=(g_candata.gun[gunid].yx_data.yx_dc_pf22[tabid]>>offset)&0x01;
//
//		if(err_code!=0)
//		{
//			memcpy(last_temp_pf22[gunid],g_candata.gun[gunid].yx_data.yx_dc_pf22,8);
//			memcpy(last_temp_pf23[gunid],g_candata.gun[gunid].yx_data.yx_dc_pf23,8);
//			return err_code;
//		}
//
//   }

	if (pconfig->devtype==DC)
	{
        // 总告警  
		tabid  = DC_IND_TOTAL_FAULT_OFFSET / 8 + 1;
		offset = DC_IND_TOTAL_FAULT_OFFSET % 8;
		err_code=(g_candata.gun[gunid].yx_data.yx_dc_pf22[tabid]>>offset)&0x01;

		err = err_code;
        // 设备运行正常，无告警 
		if (err_code == 0)
		{
			memcpy(last_temp_pf22[gunid], g_candata.gun[gunid].yx_data.yx_dc_pf22, 8);
			memcpy(last_temp_pf23[gunid], g_candata.gun[gunid].yx_data.yx_dc_pf23, 8);
			return 0;
		}

		err_code_z = err_code;  // 保存总告警标志 

        // 检索各类报警信息是否启动（CAN PF 22） 
        num = ARRAY_LEN(yxerr8704_tab);
	    for(i=0;i<num;i++)
	    {
//	    	u8 xxx[]={0x00,0x04,0x00,0x00,0x00,0x80,0x00,0x01};
//	    	u8 err_xxx;
	    	tabid =yxerr8704_tab[i].offset/8+1;
	    	offset=yxerr8704_tab[i].offset%8;
	    	err_code=(g_candata.gun[gunid].yx_data.yx_dc_pf22[tabid]>>offset)&0x01;
    	    last_err_code=(last_temp_pf22[gunid][tabid]>>offset)&0x01;
//			err_xxx=(xxx[tabid]>>offset)&0x01;
//			if (err_xxx!=0)
//			    printf("\r\nyyyyyyyyyyyyyyyyyyyerr_xxx[%d] =%d\r\n",i,yxerr8704_tab[i].offset);
	    	if (err_code != 0 && err_code < 36)
	    	{
                // 保存记录 
	    		if (last_err_code==0)
	    		{
	    			writeErrToDb(gunid,yxerr8704_tab[i].offset);
	    		}
	    		can_debug("yx_dc_pf22充电桩出现故障  故障代码=%d  %.*a",yxerr8704_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_dc_pf22);
	            if (err_code != 0)
	            {
	    		   err = yxerr8704_tab[i].offset;
                   // 添加当前生成的告警记录 
	    		   errcodeflag[0]++;
	    		   errcodeflag[errcodeflag[0]]=err;
                   // 保存当前最新的告警记录 
	    		   if(err1==0)
	    			   err1=err;

	            }

	    	}
	    	else if(err_code!=0)
	    	{
	    		can_debug(">36yx_dc_pf22充电桩出现故障  故障代码=%d  %.*a",yxerr8704_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_dc_pf22);
	    	}


	    }
        
        // 检索各类报警信息是否启动（CAN PF 23） 
	    num =	ARRAY_LEN(yxerr8960_tab);
	    can_debug("表格总条数num = %d\r\n",num);
	    can_debug("出现总故障 %.*a",8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
	    for (i=0;i<num;i++)
	    {
	    	alloff=yxerr8960_tab[i].offset;
	    	tabid=yxerr8960_tab[i].offset/8+1;
	    	offset=yxerr8960_tab[i].offset%8-1;

	    	can_debug("表格总条数num = %d 第%d条 总偏移=%d\r\n",num,i,alloff);
            // 告警状态 
	    	err_code=(g_candata.gun[gunid].yx_data.yx_dc_pf23[tabid]>>offset)&0x01;
    	    last_err_code=(last_temp_pf23[gunid][tabid]>>offset)&0x01;
 	    	if(err_code!=0)
	    	{
                // 生成告警记录 
	    		if(last_err_code==0)
	    		{
	    			writeErrToDb(gunid,yxerr8960_tab[i].offset+DC_IND_PRIVATE_VALUE_OFFSET);
	    		}
                // 更新告警记录 
	    		can_debug("yx_dc_pf23充电桩出现故障  故障代码=%d  %.*a",yxerr8960_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
	    		if(err_code!=0)//err==1 &&
	    		{
		    		ui_debug("111yx_dc_pf23充电桩出现故障  故障代码=%d  %.*a",yxerr8960_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
	    		   err = yxerr8960_tab[i].offset+DC_IND_PRIVATE_VALUE_OFFSET;
	    		   errcodeflag[0]++;
	    		   errcodeflag[errcodeflag[0]]=err;
	    		   if(err1==0)
	    			   err1=err;
	    		}
	    	}
	    }
        
        // 更新保存的遥信遥测数值 
		memcpy(last_temp_pf22[gunid],g_candata.gun[gunid].yx_data.yx_dc_pf22, 8);
		memcpy(last_temp_pf23[gunid],g_candata.gun[gunid].yx_data.yx_dc_pf23, 8);

	    can_debug("出现总故障 %.*a  %.*a",8,g_candata.gun[gunid].yx_data.yx_dc_pf22,8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
		if(err1>1)
			err=err1;

		if(err != 0)
		{
			can_debug("出现总故障 %.*a  %.*a",8,g_candata.gun[gunid].yx_data.yx_dc_pf22,8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
		}
		else if (err_code_z != 0)
		{
			errcodeflag[0] = 1;
			errcodeflag[1] = 1;
			err = 1;
		}

	    return err;

	}
	else if(pconfig->devtype==AC)
	{
		tabid=AC_IND_TOTAL_FAULT_OFFSET/8+1;
		offset=AC_IND_TOTAL_FAULT_OFFSET%8;

		err_code=(g_candata.gun[gunid].yx_data.yx_ac_pf32[tabid]>>offset)&0x01;

		err=err_code;
		if(err_code==0)
		{

			   memcpy(last_temp_pf22[gunid],g_candata.gun[gunid].yx_data.yx_ac_pf32,8);

			return 0;
		}
		else
			can_debug("交流桩出现总故障 %.*a ",8,g_candata.gun[gunid].yx_data.yx_ac_pf32);

	    num=	ARRAY_LEN(yxerr12800_tab);
	    for(i=0;i<num;i++)
	    {
//	    	u8 xxx[]={0x00,0x04,0x00,0x00,0x00,0x80,0x00,0x01};
//	    	u8 err_xxx;
	    	tabid=yxerr12800_tab[i].offset/8+1;
	    	offset=yxerr12800_tab[i].offset%8;
	    	err_code=(g_candata.gun[gunid].yx_data.yx_ac_pf32[tabid]>>offset)&0x01;
    	   last_err_code=(last_temp_pf22[gunid][tabid]>>offset)&0x01;

	    	if(err_code!=0 && err_code<28)
	    	{
	    		if(last_err_code==0)
	    		{
	    			writeErrToDb(gunid,yxerr12800_tab[i].offset);
	    		}
	    		can_debug("yx_dc_pf32充电桩出现故障  故障代码=%d  %.*a",yxerr12800_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_ac_pf32);
	            if(err_code!=0)
	            {
	    		   err = yxerr12800_tab[i].offset;
	    		   errcodeflag[0]++;
	    		   errcodeflag[errcodeflag[0]]=err;
	    		   if(err1==0)
	    			   err1=err;

	            }

	    	}
	    }

		     memcpy(last_temp_pf22[gunid],g_candata.gun[gunid].yx_data.yx_ac_pf32,8);

		if(err1>1)
			err=err1;
	    return err;
//
//
//	    for(i=0;i<num;i++)
//	    {
//	    	tabid=yxerr12800_tab[i].offset/8+1;
//	    	offset=yxerr12800_tab[i].offset%8;
//	    	err_code=(g_candata.gun[gunid].yx_data.yx_ac_pf32[tabid]>>offset)&0x01;
//	    	if(err_code!=0)
//	    		return yxerr12800_tab[i].offset;
//	    }
//	    return 1;
}
   return err_code;

}
u8 get_gun_err(u8 gunid)
{
    u8 err_code=0,err_code_z=0;
    u8 tabid;
    u8 offset;
    u8 alloff;
    int i;
    int num;
	u8 err=0;//00 04 00 00 00 80 00 01

	if(pconfig->devtype==DC)
	{
		tabid=DC_IND_TOTAL_FAULT_OFFSET/8+1;
		offset=DC_IND_TOTAL_FAULT_OFFSET%8;

		err_code=(g_candata.gun[gunid].yx_data.yx_dc_pf22[tabid]>>offset)&0x01;

		err=err_code;
		err_code_z=err_code;
		if(err_code==0)
		{
			return 0;
		}
       num=	ARRAY_LEN(yxerr8704_tab);

	    for(i=0;i<num;i++)
	    {
//	    	u8 xxx[]={0x00,0x04,0x00,0x00,0x00,0x80,0x00,0x01};
//	    	u8 err_xxx;
	    	tabid=yxerr8704_tab[i].offset/8+1;
	    	offset=yxerr8704_tab[i].offset%8;
	    	err_code=(g_candata.gun[gunid].yx_data.yx_dc_pf22[tabid]>>offset)&0x01;
//			err_xxx=(xxx[tabid]>>offset)&0x01;
//			if(err_xxx!=0)
//			    printf("\r\nyyyyyyyyyyyyyyyyyyyerr_xxx[%d] =%d\r\n",i,yxerr8704_tab[i].offset);
	    	if(err_code!=0 && err_code<36)
	    	{
	    		ui_debug("yx_dc_pf22充电桩出现故障  故障代码=%d  %.*a",yxerr8704_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_dc_pf22);
	            if(err_code!=0)
	            {
	    		   err = yxerr8704_tab[i].offset;
	    		   return err;

	            }

	    	}
	    	else if(err_code!=0)
	    	{
	    		ui_debug(">36yx_dc_pf22充电桩出现故障  故障代码=%d  %.*a",yxerr8704_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_dc_pf22);
	    	}


	    }
	    num=	ARRAY_LEN(yxerr8960_tab);
	    can_debug("表格总条数num = %d\r\n",num);
	    can_debug("出现总故障 %.*a",8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
	    for(i=0;i<num;i++)
	    {
	    	alloff=yxerr8960_tab[i].offset;
	    	tabid=yxerr8960_tab[i].offset/8+1;
	    	offset=yxerr8960_tab[i].offset%8-1;

	    	can_debug("表格总条数num = %d 第%d条 总偏移=%d\r\n",num,i,alloff);

	    	err_code=(g_candata.gun[gunid].yx_data.yx_dc_pf23[tabid]>>offset)&0x01;

 	    	if(err_code!=0)
	    	{

	    		ui_debug("yx_dc_pf23充电桩出现故障  故障代码=%d  %.*a",yxerr8960_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
	    		if(err_code_z==1 && err_code!=0)
	    		{
	    		   err = yxerr8960_tab[i].offset+DC_IND_PRIVATE_VALUE_OFFSET;
	    		   return err;
	    		}
	    	}
	    }

		ui_debug("出现总故障 %.*a  %.*a",8,g_candata.gun[gunid].yx_data.yx_dc_pf22,8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
       if(err_code_z!=0)
			err=1;

		if(err!=0)
		{
			ui_debug("出现总故障 %.*a  %.*a",8,g_candata.gun[gunid].yx_data.yx_dc_pf22,8,g_candata.gun[gunid].yx_data.yx_dc_pf23);
		}

	    return err;

	}
	else if(pconfig->devtype==AC)
	{
		tabid=AC_IND_TOTAL_FAULT_OFFSET/8+1;
		offset=AC_IND_TOTAL_FAULT_OFFSET%8;

		err_code=(g_candata.gun[gunid].yx_data.yx_ac_pf32[tabid]>>offset)&0x01;

		err=err_code;
		if(err_code==0)
		{

			return 0;
		}
		else
			ui_debug("交流桩出现总故障 %.*a ",8,g_candata.gun[gunid].yx_data.yx_ac_pf32);

	    num=	ARRAY_LEN(yxerr12800_tab);
	    for(i=0;i<num;i++)
	    {
//	    	u8 xxx[]={0x00,0x04,0x00,0x00,0x00,0x80,0x00,0x01};
//	    	u8 err_xxx;
	    	tabid=yxerr12800_tab[i].offset/8+1;
	    	offset=yxerr12800_tab[i].offset%8;
	    	err_code=(g_candata.gun[gunid].yx_data.yx_ac_pf32[tabid]>>offset)&0x01;

	    	if(err_code!=0 && err_code<28)
	    	{
	    		ui_debug("yx_dc_pf32充电桩出现故障  故障代码=%d  %.*a",yxerr12800_tab[i].offset,8,g_candata.gun[gunid].yx_data.yx_ac_pf32);
	            if(err_code!=0)
	            {
	    		   err = yxerr12800_tab[i].offset;
	    		   return err;

	            }

	    	}
	    }
	    return err;

}
   return err_code;

}




int StartChargeCan01(u8 gunid,void* pdata)//启动确认帧
{
	static StartInfo ppp;//=NULL;//=(StartInfo *)pdata;
	start_mx* p = (start_mx*) pdata;
	g_uidata->cmd2[gunid].guntab = gunid;//注意：充电过程中控制器自行停止充电
	u8 _err_=0;
//	g_stop_detail[gunid]=0;
	if(g_candata.errcode[gunid]==0 )
    	_err_=get_gun_err(gunid);

	DEBUG_SHOW1("查看充电启动结果");
	DEBUG_SHOW1("查看充电启动结果  gunid=%d  %x MX1=%d  MX2=%d  MX3=%d！！！！！！！",gunid,g_candata.gun[gunid].yx_data.yx_dc_pf22[1],p->MX1,p->MX2,p->MX3);
	StartInfo *pp=&ppp;//=(StartInfo *)pdata;
	pp->p_startInfo=p;
	if (p->MX2 == 0)
	{
		   DEBUG_SHOW1("11充电启动成功11  gunid=%d   %x MX1=%d  MX2=%d  MX3=%d！！！！！！！",gunid,g_candata.gun[gunid].yx_data.yx_dc_pf22[1],p->MX1,p->MX2,p->MX3);
		   pp->p_startInfo->MX3=0;
		   gm_sys_state[gunid] = _SYS_WAIT_CHARGING_START_;
#ifdef XJ_MQTT_CLIENT
    	   g_msg_save[gunid] = _MSG_SAVE_START_;
#endif

	}
	else
	{

		ui_debug("01命令充电启动失败！！！！！！！gunid=%d",gunid);
	    g_stop_reason[gunid]=5;
	    if(p->MX3==MAIN_STOP_FIN)//can故障
	    {
			if(g_candata.errcode[gunid])
			{
				g_stop_detail[gunid]=400+(g_candata.errcode[gunid]-1);
			}
			else if(meter_err_state[gunid]==1)
			{

				g_stop_detail[gunid]=MT_COMM_ERR;
			}
			else if(card_err_state[gunid]==1)
			{
				g_stop_detail[gunid]=CARD_COMM_ERR;
			}

	    }
	    else if(p->MX3==OVER_TIME_PF01)
	    {
	    	g_stop_detail[gunid]=CHA_OVERBACK_PF01;
	    }
	    else if(p->MX3==SET_COMB_FAIL)//共充设置失败
	    {
	    	g_stop_detail[gunid]=COMB_SET_FAIL;
	    }
#ifdef NO_ERR_300
	    else if(p->MX3==36 && _err_!=0)
	    {
	    	g_stop_detail[gunid]=300+_err_;
	    }
#endif
	    else
	    {
	    	ui_debug("充电启动失败！！！！！！！gunid=%d g_stop_detail[gunid]=p->MX3=%d",gunid,g_stop_detail[gunid]=p->MX3);
    		g_stop_detail[gunid]=p->MX3;
	    }

		if (gm_sys_state[gunid] == _SYS_WAIT_CHARGING_START_) {
			g_uidata->cmd2[gunid].result = 2;
			g_sss[gunid] = 0;
			if (g_ifApp[gunid] == _APP_MODE_) {
				g_sss[gunid] = 5;
				g_ifApp[gunid] = _APP_WAIT_STOP_;
			} else
				g_ifApp[gunid] = _CARD_WAIT_STOP_;

			// 	g_ifApp[gunid]=_IDEL_MODE_;
			gm_sys_state[gunid] = _SYS_START_FAIL_;

		}


		ui_debug("充电启动失败！！！！！！！gunid=%d  g_stop_detail[gunid]=%d",gunid,g_stop_detail[gunid]);
		p->MX2=1;
#ifdef NW_CLIENT
		pp->p_chargepara=NULL;
	    pp->p_startInfo->MX3=g_stop_detail[gunid];
	    if(g_uidata->net_state==1)
	    {
    		ui_debug("111充电启动结果传送到平台");

	    	if(main_FinStartCharge!=NULL)
	    	{
	    		ui_debug("222充电启动结果传送到平台");
		        main_FinStartCharge(gunid,(void*)pp);//启动过程没有错误，等待控制器启动
	    	}
	    }
#endif

	}
#ifdef XJ_MQTT_CLIENT
	   printf("充电结果发往主站！！！！！\r\n");
		if(g_charge_arg[gunid].startmode==_CARD_MODE_)
			pp->p_chargepara=&g_charge_arg[gunid];
	//	if(g_uidata->net_state==1)
		pp->p_startInfo->MX2=p->MX2;
	    pp->p_startInfo->MX3=g_stop_detail[gunid];
	    if(g_uidata->net_state==1)
	    {
	 	   printf("1111111111111充电结果发往主站！！！！！\r\n");

	    }

#endif

#ifdef QL_CLOUD_CLIENT
           printf("充电结果发往主站！！！！！\r\n");
           if(g_charge_arg[gunid].startmode==_CARD_MODE_)
                pp->p_chargepara=&g_charge_arg[gunid];

            pp->p_startInfo->MX2=p->MX2;
            pp->p_startInfo->MX3=g_stop_detail[gunid];
            if(g_uidata->net_state==1)
            {
               printf("1111111111111充电结果发往主站！！！！！\r\n");
               //20220703 add by cz
               if (pp->p_startInfo->MX2 == 1)
               {
            	   pp->p_startInfo->MX3 = p->MX3;
                   if (main_FinStartCharge != NULL)
                   {
                      sprintf(_tmp_print_str,"启动充电0102结果发往主站  成功标识 =%d  失败原因=%d \n",pp->p_startInfo->MX2,pp->p_startInfo->MX3);
                      //fs_debug_104(_tmp_print_str);
                       main_FinStartCharge(gunid, (void*)pp);//启动过程没有错误，等待控制器启动
                   }
                }
               /*
                if(main_FinStartCharge!=NULL)
                {
                	sprintf(_tmp_print_str,"启动充电0102结果发往主站  成功标识 =%d  失败原因=%d \n",pp->p_startInfo->MX2,pp->p_startInfo->MX3);
                	fs_debug_104(_tmp_print_str);
                    main_FinStartCharge(gunid,(void*)pp);//启动过程没有错误，等待控制器启动
                }
                */
            }
    
#endif
	g_uidata->gunmsg[gunid].stopreason=g_stop_reason[gunid];
	g_uidata->gunmsg[gunid].m_stopReason=g_stop_detail[gunid];

	return 0;

}

//#ifdef		NW_CLIENT
//
//		if(g_chargepara[gunid].startmode==_CARD_MODE_)
//			pp->p_chargepara=&g_chargepara[gunid];
//#endif


start_mx   px;
int FinishStartCharge(u8 gunid,void* pdata)//启动完成帧
{
	static StartInfo ppp;//=NULL;//=(StartInfo *)pdata;
	 px =* (start_mx*) pdata;
	start_mx* p = &px;
	StartInfo *pp=&ppp;//=(StartInfo *)pdata;
	u8 _err_=0;
    
	g_stop_detail[gunid]=0;
	if (g_candata.errcode[gunid]==0 )
    	_err_ = get_gun_err(gunid);     // 获取当前告警，存在任何一个告警都置1

	g_uidata->cmd2[gunid].guntab = gunid;   //注意：充电过程中控制器自行停止充电
	DEBUG_SHOW1("查看充电结果");
	DEBUG_SHOW1("查看充电结果  gunid=%d  %x MX1=%d  MX2=%d  MX3=%d！！！！！！！",gunid,g_candata.gun[gunid].yx_data.yx_ac_pf32[1],p->MX1,p->MX2,p->MX3);
	pp->p_startInfo = p;
    
//		if(g_charge_arg[gunid].startmode==_CARD_MODE_)
    pp->p_chargepara = NULL;//&g_charge_arg[gunid];
    
	if (p->MX2 == 0)
	{
		DEBUG_SHOW1("11充电启动成功11  gunid=%d   %x MX1=%d  MX2=%d  MX3=%d！！！！！！！",gunid,g_candata.gun[gunid].yx_data.yx_ac_pf32[1],p->MX1,p->MX2,p->MX3);
		g_uidata->cmd2[gunid].result = 1;
		gm_sys_state[gunid] =_SYS_START_FIN_;
		pp->p_startInfo->MX3=0;
        
#ifdef NW_CLIENT
		g_msg_save[gunid] = _MSG_SAVE_START_;
		if(g_chargepara[gunid].startmode==_CARD_MODE_)
		{
			pp->p_chargepara = &g_chargepara[gunid];
		}
#endif

#ifdef XJ_MQTT_CLIENT
		pp->p_startInfo->MX2 = 2;
#endif

#ifdef QL_CLOUD_CLIENT
        pp->p_startInfo->MX2 = 0;   //负荷控制开关关闭 20210619 pp->p_startInfo->MX2 = 2;
#endif

	}
	else
	{
		ui_debug("充电启动失败！！！！！！！gunid=%d",gunid);
	    g_stop_reason[gunid] = 5;   //停止充电原因： 5 - 充电桩故障
		
	    if (p->MX3==MAIN_STOP_FIN)  //  can故障 _ERR_CODE: 故障 
	    {
			if (g_candata.errcode[gunid])
			{
				g_stop_detail[gunid] = 400 + (g_candata.errcode[gunid]-1);
			}
			else if (meter_err_state[gunid] == 1)
			{
				g_stop_detail[gunid] = MT_COMM_ERR; //247
			}
			else if (card_err_state[gunid] == 1)
			{
				g_stop_detail[gunid] = CARD_COMM_ERR;
			}
	    }
	    else if(p->MX3==OVER_TIME_PF01)
	    {
	    	g_stop_detail[gunid] = CHA_OVERBACK_PF01;
	    }
	    else if(p->MX3==OVER_TIME_PE11)
	    {
	    	g_stop_detail[gunid] = CHA_OVERBACK_PE11;
	    }
#ifdef	NO_ERR_300
	    else if(p->MX3==140 && _err_!=0)
	    {
	    	g_stop_detail[gunid] = 300+_err_;
	    }
#endif
	    else
	    {
	    	ui_debug("充电启动失败！！！！！！！gunid=%d g_stop_detail[gunid]=p->MX3=%d",gunid,g_stop_detail[gunid]=p->MX3);
	    	//20210703 add by cz CAN库中对于CCU传过来的故障码在故障时，增加100的偏移 这里进行处理
	    	g_stop_detail[gunid] = (p->MX3 >100) ? (p->MX3 -100):p->MX3 ;
	    }
		printf("000充电结果发往主站！！！！！ gm_sys_state[gunid] =%d\r\n",gm_sys_state[gunid]);

		if (gm_sys_state[gunid] == _SYS_WAIT_CHARGING_START_)// || gm_sys_state[gunid] == _SYS_START_FIN_) 
		{
		    printf("111充电结果发往主站！！！！！     gm_sys_state[gunid] =%d\r\n",gm_sys_state[gunid]);

			g_uidata->cmd2[gunid].result = 2;   // 充电失败 
			g_sss[gunid] = 5;                   // 
			if (g_ifApp[gunid] == _APP_MODE_)
				g_ifApp[gunid] = _APP_WAIT_STOP_;       // 
			else
				g_ifApp[gunid] = _CARD_WAIT_STOP_;      // 

			gm_sys_state[gunid] = _SYS_START_FAIL_;     
			pp->p_startInfo->MX2 = 3;
		}
		else
		{
			pp->p_startInfo->MX2=1;
		}
		   ui_debug("充电启动失败！！！！！！！gunid=%d  g_stop_detail[gunid]=%d",gunid,g_stop_detail[gunid]);
		   printf("222充电结果发往主站！！！！！     gm_sys_state[gunid] =%d\r\n",gm_sys_state[gunid]);

		//	if(g_uidata->net_state==1)
		    pp->p_startInfo->MX3 = g_stop_detail[gunid];


    }
    
    if(g_uidata->net_state==1)
    {
        if(pp->p_startInfo->MX2==1)
        {
		    sprintf(_tmp_print_str,"充电启动0102结果发往主站  成功标识 =%d  失败原因=%d gunid=%d\n",pp->p_startInfo->MX2,pp->p_startInfo->MX3,gunid);
        }
        else if(pp->p_startInfo->MX2==3)
        {
    		sprintf(_tmp_print_str,"充电完成1112结果发往主站  成功标识 =%d  失败原因=%d gunid=%d\n",pp->p_startInfo->MX2,pp->p_startInfo->MX3,gunid);
        }
        else
        	sprintf(_tmp_print_str,"充电完成结果发往主站  成功标识 =%d  失败原因=%d gunid=%d\n",pp->p_startInfo->MX2,pp->p_startInfo->MX3,gunid);

	    //fs_debug_104(_tmp_print_str);
    	if(main_FinStartCharge!=NULL)
	       main_FinStartCharge(gunid,(void*)pp);
    }

	g_uidata->gunmsg[gunid].stopreason	 = g_stop_reason[gunid];
	g_uidata->gunmsg[gunid].m_stopReason = g_stop_detail[gunid]; // 充电桩故障原因
    
	return 0;
}

int FinishStopCharge(u8 gunid,void* pdata)
{
    //粤易充	1.本地刷卡终止，2.远程终止充电，3充满自动停止，4余额不足，5充电桩故障，6 BMS故障，7、急停按钮停止，
    //8.验证码停止，9.停电结束，10.按电量满足结束，11.按金额满足结束，12.按时间满足结束，13.拔枪结束，

    //羊城充（不用）1本地刷卡终止，2远程终止充电，3充满自动停止，4余额不足，5充电桩故障，6 BMS故障   	7、急停按钮停止
    //8充电时间到自动停止 9充电金额到自动停止 10充电电量到自动停止
	//	高字节 正常上传标识
	//	0正常，1通讯故障补传，2停电补传，256其它
	end_mx* p = (end_mx*) pdata;
	//msgNW  msg;
	u8 stopreason = g_stop_reason[gunid];
	u8 _err_=0;

	if(g_candata.errcode[gunid]==0 )
    	_err_=get_gun_err(gunid);
	ui_debug("收到停止充电完成回应！！！！g_stop_reason=%d p->MX1=%x",g_stop_reason[gunid],p->MX1);
	if(gm_sys_state[gunid] != _SYS_START_FIN_ && gm_sys_state[gunid] != _SYS_WAIT_STOP_  && gm_sys_state[gunid] != _SYS_START_FAIL_
			&& gm_sys_state[gunid] !=_SYS_WAIT_STOP_1_)
	{
		ui_debug("收到不应该收到的停止充电完成回应 gm_sys_state[%d]=%d",gunid,gm_sys_state[gunid]);//
		return 1;
	}
	g_stop_detail[gunid]=0;
//	if(gm_sys_state[gunid] == _SYS_START_FAIL_ || gm_sys_state[gunid] ==_SYS_WAIT_STOP_1_ )
//	{
//	    if(card_err_state[gunid]==1)//g_ifApp[gunid]==1 ||
//	    	g_sss[gunid]=25;
//	    else
//	    {
//	    	g_sss[gunid]=0;
//
//	        g_uidata->cmd2[gunid].result = 2;
//	    }
//	     gm_sys_state[gunid] =_SYS_START_FAIL_;
//	}
//	else
    gm_sys_state[gunid]=_SYS_STOP_FIN_;
    if(g_ifApp[gunid]==_APP_MODE_)
    	g_ifApp[gunid]=_IDEL_MODE_APP_;
    else
    	g_ifApp[gunid]=_IDEL_MODE_CARD_;
	g_uidata->cmd4[gunid].guntab = gunid;
	if (p->MX2 == 0)
		g_uidata->cmd4[gunid].result = 1;
	else
		g_uidata->cmd4[gunid].result = 1;
	g_uidata->gunmsg[gunid].charge_state = 4; //4 表示充电结束, 停止完成，充电结束 zhouhao 2021-07-14

	if (g_stop_reason[gunid]!=0)
	{
		ui_debug("充电停止原因  g_stop_reason[%d]=%d",gunid,g_stop_reason[gunid]);//充电结果发往主站
		stopreason=g_stop_reason[gunid];
	}
	else if((pconfig->devtype==DC && p->MX1==8) || (pconfig->devtype==AC && p->MX1==7))
	{
	    stopreason=7;
	}
//	else if(p->MX1==0x2b)
//	{
//		stopreason=6;
//	}
	else if(p->MX1==0x2a)
	{
		stopreason=3;
	}
	else if(p->MX1>0)
	{
		stopreason=5;
	}
	else if(_err_!=0)
	{
//		 if(pconfig->devtype==DC &&_err_==DC_IND_BMS_COMMUNICATION_OFFSET)
//		    stopreason=6;
		 if((pconfig->devtype==DC && _err_==DC_IND_EMERSTOP_FAULT_OFFSET) || ( pconfig->devtype==AC && _err_==AC_IND_EMERSTOP_OFFSET))
			 stopreason=7;

		 else
			 stopreason=5;
	}

	else
		stopreason=0xff;
	if(stopreason==5)
	{
		if(g_candata.errcode[gunid])
		{
            if( (g_candata.errcode[gunid] & 1)>0)
           {
            	g_stop_detail[gunid]=CAN_COMM_ERR1;//g_candata.errcode[gunid];

           }
           else if((g_candata.errcode[gunid] & 2)>0)
           {
        	   g_stop_detail[gunid]=CAN_COMM_ERR2;//g_candata.errcode[gunid];

           }
           else if((g_candata.errcode[gunid] & 4)>0)
           {
        	   g_stop_detail[gunid]=CAN_COMM_ERR3;//g_candata.errcode[gunid];

           }
			printf("打印充电停止原因  g_stop_detail[%d]=%d",gunid,g_stop_detail[gunid]);
		}
		else if(meter_err_state[gunid]==1)
		{
			g_stop_detail[gunid]=MT_COMM_ERR;
		}
		else if(card_err_state[gunid]==1)
		{
			g_stop_detail[gunid]=CARD_COMM_ERR;
		}
//		else if(g_ifApp[gunid]==_APP_MODE_ && g_uidata->net_state==0)
//		{
//			g_stop_detail[gunid]=NET_CLOSED;
//		}
		else if(p->MX1==GO_STOP_CHA)
			g_stop_detail[gunid]=CHARGE_STOP_UNEXP;
		else if(p->MX1==OVER_TIME_PF03)
			g_stop_detail[gunid]=OVER_TIME_PF03;
		else if(p->MX1==OVER_TIME_PF03)
			g_stop_detail[gunid]=OVER_TIME_PF13;
#ifdef	NO_ERR_300
		else if((p->MX1==2 || p->MX1==45) && _err_!=0)
		{
			g_stop_detail[gunid]=300+_err_;
		}
#endif
		else if(p->MX1>0)
			g_stop_detail[gunid]=200+p->MX1;
#ifdef	    NO_ERR_300
		else if(_err_!=0)
		{
			//g_stop_detail[gunid]=232;
			g_stop_detail[gunid] = 300+_err_;
		}
#endif
		else
			g_stop_detail[gunid] = 399;
	}
	else if(stopreason==14)
	{
		g_stop_detail[gunid]=247;//MT_DATA_ERR;
		stopreason=5;
	}

	//p->MX1=stopreason;
	//ui_debug("111充电停止原因  g_stop_reason[%d]=%d",gunid,stopreason);  //收到来自枪号0的充电启动成功消息
	ui_debug("111充电停止原因  g_stop_reason[%d]=%d p->MX1=0x%x",gunid, stopreason, p->MX1);  //收到来自枪号0的充电启动成功消息
	g_stop_reason[gunid]=stopreason;

	//protocol_104_StopCharge(gunid, pdata,(void*)&cur_record);100+
	//if(g_uidata->net_state==1 && g_ifApp[gunid]==1)
#ifdef XJ_MQTT_CLIENT
	ui_debug("向主站报告充电停止结果！！！！！！");

	if(main_FinStopCharge!=NULL)
	{
		ui_debug("111111向主站报告充电停止结果！！！！！！");

	   main_FinStopCharge(gunid, pdata);
//	   sprintf(_tmp_print_str,"gunno=%d主控收到充电完成  原因=%d  %d\n ",gunid,g_stop_reason[gunid],g_stop_detail[gunid]);
//	   fs_debug_104(_tmp_print_str);
	}
#endif

#ifdef NW_CLIENT
	   main_FinStopCharge(gunid, pdata);
#endif

#ifdef QL_CLOUD_CLIENT
       if (main_FinStopCharge!=NULL)
           main_FinStopCharge(gunid, pdata);
#endif

    if(g_ifApp[gunid]==_APP_MODE_)
    	g_ifApp[gunid]=_IDEL_MODE_APP_;
    else
    	g_ifApp[gunid]=_IDEL_MODE_CARD_;

    printf("改变状态保存数据！！！！！gm_sys_state[gunid]=%d ret:%d \r\n",gm_sys_state[gunid], p->MX1);
    ui_debug("收到停止充电完成回应！！！！stopreason=%d",stopreason);
     return 0;

}


int update_Yc(u8 gunid,void* pdata)
{
    int ret=0;

    union u_out_mx *p=(union u_out_mx *)pdata;
    ycdata_main[gunid]=*p;
    ui_debug("收到来自CAN的遥测数据！！！！");

#ifdef XJ_MQTT_CLIENT

    if(main_updateYC!=NULL)
       main_updateYC(gunid, pdata);
#endif
#ifdef NW_CLIENT
    if(main_updateYC!=NULL)
         main_updateYC(gunid, pdata);
#endif

#ifdef ORDERLY_CHARGE
    if(protocol_MAS_updateMX_fun!=NULL)
    {
         protocol_MAS_updateMX_fun(gunid,(void*)&g_candata.gun[gunid].yc_data);
    }
#endif

#ifdef QL_CLOUD_CLIENT
        if(main_updateYC!=NULL)
            main_updateYC(gunid, pdata);
#endif
	return ret;
}


int update_Yx(u8 gunid,void* pdata)
{

    out_yx *pyxdata = (out_yx *) pdata;
    main_yx temp;
    temp.errcode=g_candata.errcode[gunid];
    temp.yx_data=*pyxdata;

    ui_debug("收到来自CAN的遥信数据！！！！gunid=%d",gunid);

   // ui_debug1("收到来自CAN[%d]的遥信数据！！！！yx_dc_pf22=%.*a",gunid,8,pyxdata->yx_dc_pf22);
#ifdef XJ_MQTT_CLIENT
    if(main_updateYX!=NULL)
    main_updateYX( gunid, (void*)&temp);
#endif
#ifdef NW_CLIENT
    if(main_updateYX!=NULL)
        main_updateYX(gunid,(void *)pdata);
#endif

#ifdef QL_CLOUD_CLIENT
    if(main_updateYX!=NULL)
        main_updateYX( gunid, (void*)&temp);
#endif

#ifdef ORDERLY_CHARGE
	if(protocol_MAS_updateST_fun!=NULL)
	   protocol_MAS_updateST_fun(gunid,(void *)pdata);
#endif
	return 0;
}

//ctrlpw_bak bakdata;
//int bak_ctrl_pw(u8 gunid,void* pdata)
//{
//	bakdata=*(ctrlpw_bak *)pdata;
//    printf("功率调节回调函数   gunid=%d   type=%d  value=%d\r\n",gunid,bakdata.ctrltype,bakdata.ctrlvalue);
//
////	xx.ctrlvalue=value*10;
////	xx.ctrltype=type;
////	xx.result=ret;
//
//    bakdata.ctrlvalue*=10;
//#ifdef ORDERLY_CHARGE
//    if(finAdjPw_fun!=NULL)
//    	finAdjPw_fun( gunid, (void *)&bakdata);
//#endif
//	return 0;
//}

void initcan_main(pconf conf)
{
    char* p=NULL;
    gpcan->firm_id=conf.firm_id;
	gpcan->cannum=conf.cannum;
	gpcan->pgun_info=&gun_can_info_tab[0];
//	gpcan->gunno_1st=conf.gunno_1st;
//	gpcan->gunno_2nt=conf.gunno_2nt;
//	gpcan->canaddr[0]=conf.canaddr1;
//	gpcan->canaddr[1]=conf.canaddr2;
//    gpcan->qmegid[0]=g_qmegid[0];


//	if(gpcan->cannum==2)
//	{
//	    gpcan->gunnum=1;//(u8)conf.gunnum;
//	//    gpcan->qmegid[1]=g_qmegid[1];
//    }
//	else
//	{
//
//	    gpcan->gunnum=(u8)conf.gunnum;
////		if( gpcan->gunnum==2)
////			 gpcan->qmegid[1]=g_qmegid[1];
//	}

    gpcan->gunnum=(u8)conf.gunnum;
	gpcan->p_can[0]=g_pcan[0];
	gpcan->p_can[1]=g_pcan[1];

	conf.devNO[16]='\0';
	can_debug("交给can的设备号 %s \r\n",conf.devNO);  
    strBcd2BcdArray(conf.devNO,gpcan->devNo);
    gpcan->type=conf.devtype;
    gpcan->send2cha=TcuSendToCha;
    gpcan->StartCharge01=StartChargeCan01;

    gpcan->finStartCharge=FinishStartCharge;
    gpcan->finStopCharge=FinishStopCharge;

    gpcan->outyx=update_Yx;
    gpcan->outyc=update_Yc;
    gpcan->writelog=fs_debug_104;
//#ifdef XJ_MQTT_CLIENT
//    gpcan->outBMS=update_Bms;
//#endif

	p = strstr(conf.can_ver, ".");
    conf.can_ver[strlen(conf.can_ver)]=0x00;

	gpcan->can_ver[0]=byte2bcd(atoi(p+1));

	*p=0x00;
	gpcan->can_ver[1]=byte2bcd(atoi(conf.can_ver));
    gpcan->data2main=&g_candata;
    gpcan->ctrlpw_type=conf.ctrlpw_type;
     protocol_can_init((void*)gpcan);
	can_debug("交给can的设备号 %s \r\n",conf.devNO);

}
